#pragma once
#include "TCPserver.hpp"
#include <memory>
#include "socket.hpp"
#include <unordered_map>
#include "Util.hpp"
#include "log.hpp"
#include <functional>
#include <sstream>


const std::string gspace = " ";
const std::string glinespace = "\r\n";
const std::string gsp = ": ";
const std::string webroot = "./webroot";
const std::string homepage = "/homepage.html";
const std::string page_404 = "/page_404.html";
using namespace socketmodule;
using namespace logmodule;

class HtppRequest
{
    public:
    HtppRequest():_isinteract(false)
    {}
    bool serialize()
    {
        return true;
    }
    void ParseReqline(std::string &reqline)
    {
        std::stringstream ss(reqline);
        ss>>_method>>_url>>_version;
    }
    bool deserialize(std::string &str)
    {
        //提取请求行
        std::string reqline;
        bool res = util::Readoneline(str,&reqline,glinespace);
        LOG(loglevel::DEBUG)<<"readoneline";
        //对请求行进行反序列化
        ParseReqline(reqline);
        if(_url== "/")
        {
            _url = webroot+_url+homepage;
        }
        else
        {
            _url = webroot+_url;
        }
        auto pos = _url.find("?");
        std::string temp = "?";
        if(pos == std::string::npos)
        {
            return true;//只是一次普通的请求
        }
        _args = _url.substr(pos+temp.size());
        _url = _url.substr(0,pos);
        _isinteract = true;
        return true;
    }
    std::string Uri()
    {
        return _url;
    }
    bool IsInteract()
    {
        return _isinteract;
    }
    std::string Args()
    {
        return _args;
    }
    ~HtppRequest()
    {}
    private:
    std::string _method;
    std::string _url;
    std::string _version;

    std::unordered_map<std::string,std::string> _header;
    std::string _headline;
    std::string _text;
    std::string _args;
    bool _isinteract;//是否需要交互
};

class HttpResponse
{
    public:
    HttpResponse():_blankline(glinespace)
    {}
    std::string serialize()//把字符串拼接在一起
    {
       std::string _statusline = _version+gspace+std::to_string(_code)+gspace+_codedetail+glinespace;
       std::string resp_header;
       for(auto &head:_headerr)
       {
        std::string line = head.first+ gsp+head.second+glinespace;
        resp_header+=line;
       }
       
       return _statusline+resp_header+_blankline+_textr;
        
    }
    bool deserialize()
    {
        return true;
    }
    void SetTargetfile(const std::string &target)
    {
        _targetfile = target;
    }
    void SetCode(int code)
    {
        _code = code;
        switch (_code)
        {
        case 200:
        _codedetail = "OK";
            /* code */
            break;
        case 404:
        _codedetail = "NotFound";
        break;
        default:
            break;
        }
    }
    void SetHeader(const std::string &key,const std::string &value)
    {
        auto iter = _headerr.find(key);
        if(iter != _headerr.end())
        {
            return ;
        }
        _headerr.insert(std::make_pair(key,value));
    }
    std::string Urisuffix(const std::string &filename)
    {
        //转化文件后缀符号
        auto pos = filename.rfind('.');
        if(pos = std::string::npos)
        {
            return "text/html";
        }
       std::string suffix = filename.substr(pos);
       if(suffix==".html"||suffix == ".htm")
       return "text/html";
      else if(suffix==".jpg")
       return "image.jpg";
       else if(suffix==".png")
       return "image/png";
       else
       return "";
    }
    bool MakeResponse()
    {
        //忽略小图标
         if(_targetfile == "./wwwweb/favicon.ico");
         {
            LOG(loglevel::DEBUG)<<"Ignore it";
            return false;
         }
         if(_targetfile == ".webroot/redir_test")
         {
            SetCode(302);
            SetHeader("Location","https://www.qq.com/");//临时重定向
            return true;
         }
        bool res = util::readFileContent(_targetfile,&_textr);
        int filesize = 0;
        if(!res)
        {
           
            // SetCode(404);
            // _targetfile = webroot+page_404;
            //    filesize = util::Filesize(_targetfile);
            // util::readFileContent(_targetfile,&_textr);
            //  SetHeader("Content-length",std::to_string(filesize));
            SetCode(302);
            SetHeader("Location","https://www.qq.com/");//临时重定向
            return true;
        }
        else{
            SetCode(200);//读取成功
             filesize = util::Filesize(_targetfile);
             std::string suffix =  Urisuffix(_targetfile);
             SetHeader("Content-type",suffix);
            SetHeader("Content-length",std::to_string(filesize));
        }
        return true;
    }
    ~HttpResponse()
    {}
    //private:
    std::string _version;
    int _code;//状态码
    std::string _codedetail;//状态码描述

    std::unordered_map<std::string,std::string> _headerr;
    std::string _headliner;
    std::string _textr;
    std::string _blankline;

    //其他属性
    std::string _targetfile;
};
//返回静态资源
//提供动态交互
using http_func_t  = std::function<void(HtppRequest &req,HttpResponse &resp)>;

class Http 
{
    public:
    Http(uint16_t port):tsver(std::make_unique<TcpServer>(port))
    {}
    
    void handerrequest(std::shared_ptr<Socket>& sock,inetaddr& client)
    {
         std::string httpstr;
        //我们假设读取到了完整的报文
        int n = sock->Recv(&httpstr);//浏览器发过来的大http字符串
        //读到空行，就读完了报文的报头
        //对报头进行反序列化
        if(n>0)
        {
            //对报文进行完整性分析
            HtppRequest req;
            req.deserialize(httpstr);
            std::string filename = req.Uri();
            HttpResponse resp;
            // resp._version = "HTTP/1.1";
            // resp._code = 200;
            // resp._codedetail = "OK";
            // bool res = util::readFileContent(filename,&(resp._textr));
            // (void)res;
            // std::string response_str = resp.serialize();
            // sock->Send(response_str);
            resp.SetTargetfile(req.Uri());
            resp.MakeResponse();
         std::string response_str =resp.serialize();
        }
#ifdef DEBUG
//#define DEBUG
        std::string httpstr;
        //我们假设读取到了完整的报文
        sock->Recv(&httpstr);//浏览器发过来的大http字符串
        std::cout<<httpstr;
        //直接构建应答

        HttpResponse resp;
        resp._version = "HTTP/1.1";
        //resp.deserialize
#endif
//进行反序列化

    }
    void Start()
    {
        tsver->start([this](std::shared_ptr<Socket>& sock,inetaddr& client){
            this->handerrequest(sock,client);
        });
    }
    void RegisterService(std::string name,http_func_t hander)
    {
        std::string key = webroot+ name;
        auto iter = name;
    }
    ~Http()
    {}
    private:
    std::unique_ptr<TcpServer> tsver;
    std::unordered_map<std::string, http_func_t> _hander;
};